package com.xyht.sca_s.student_manage_system.modules.asset.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.CategoryNode;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.SmsAssetCategoryManagement;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.SmsAssetFixedStorage;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.req.SmsAssetCategoryManagementReq;
import com.xyht.sca_s.student_manage_system.modules.asset.entity.resp.SmsAssetCategoryManagementResp;
import com.xyht.sca_s.student_manage_system.modules.asset.mapper.SmsAssetCategoryManagementMapper;
import com.xyht.sca_s.student_manage_system.modules.asset.mapper.SmsAssetFixedStorageMapper;
import com.xyht.sca_s.student_manage_system.modules.asset.service.SmsAssetCategoryManagementService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.modules.asset.util.CategoryUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.CategoryDeleteFlagConstant.CATEGORY_DELETE_FLAG_FALSE;
import static com.xyht.sca_s.student_manage_system.modules.asset.constant.CategoryDeleteFlagConstant.CATEGORY_DELETE_FLAG_TRUE;

/**
 * <p>
 * 资产管理类别管理 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-05-10
 */
@Service
public class SmsAssetCategoryManagementServiceImpl extends ServiceImpl<SmsAssetCategoryManagementMapper, SmsAssetCategoryManagement> implements SmsAssetCategoryManagementService {
    @Resource
    private SmsAssetCategoryManagementMapper smsAssetCategoryManagementMapper;
    @Resource
    private CategoryUtil categoryUtil;
    @Resource
    private SmsAssetFixedStorageMapper smsAssetFixedStorageMapper;


    @Override
    @Transactional
    public ResponseResult addCategory(SmsAssetCategoryManagementReq categoryReq) {
        if (isNullOrEmpty(categoryReq.getCategoryName()) || isNullOrEmpty(categoryReq.getParentId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        Integer repeatCount = smsAssetCategoryManagementMapper.selectCount(new QueryWrapper<SmsAssetCategoryManagement>()
                .lambda()
                .eq(SmsAssetCategoryManagement::getCategoryName, categoryReq.getCategoryName()));
        if (repeatCount > 0) {
            return CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_REPEAT);
        }

        if (categoryReq.getParentId().equals("0")) {
            Integer rootCategoryCount = smsAssetCategoryManagementMapper.selectCount(new QueryWrapper<SmsAssetCategoryManagement>()
                    .lambda()
                    .eq(SmsAssetCategoryManagement::getParentId, "0"));
            String category_id = rootCategoryCount + 1 + "";
            SmsAssetCategoryManagement addCategory = new SmsAssetCategoryManagement();
            addCategory.setId(category_id);
            addCategory.setRootParentId(category_id);
            addCategory.setParentId("0");
            addCategory.setCategoryName(categoryReq.getCategoryName());
            addCategory.setIsCanDelete(1);
            addCategory.setChildNum(0);
            smsAssetCategoryManagementMapper.insert(addCategory);
        } else {
            SmsAssetCategoryManagement categoryManagement = smsAssetCategoryManagementMapper.selectById(categoryReq.getParentId());
            if (categoryManagement == null || isNullOrEmpty(categoryManagement.getId())) {
                return CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_PARENT_NOT_EXIST);
            }

            SmsAssetCategoryManagement addCategory = new SmsAssetCategoryManagement();
            String category_id = categoryUtil.generateCategoryID(categoryManagement.getRootParentId(), categoryManagement.getChildNum());
            addCategory.setId(category_id);
            addCategory.setChildNum(0);
            addCategory.setIsCanDelete(1);
            addCategory.setCategoryName(categoryReq.getCategoryName());
            addCategory.setParentId(categoryReq.getParentId());
            addCategory.setRootParentId(categoryManagement.getRootParentId());
            smsAssetCategoryManagementMapper.insert(addCategory);

            SmsAssetCategoryManagement rootCategoryManagement = smsAssetCategoryManagementMapper.selectById(categoryManagement.getRootParentId());
            SmsAssetCategoryManagement updateCategory = new SmsAssetCategoryManagement();
            updateCategory.setId(rootCategoryManagement.getId());
            updateCategory.setChildNum(rootCategoryManagement.getChildNum() + 1);
            smsAssetCategoryManagementMapper.updateById(updateCategory);
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult getCategoryTree() {
        List<CategoryNode> list = smsAssetCategoryManagementMapper.selectList(new QueryWrapper<SmsAssetCategoryManagement>()
                .orderByAsc("id*1"))
                .stream()
                .map(category -> {
                    CategoryNode categoryNode = new CategoryNode();
                    BeanUtils.copyProperties(category, categoryNode);
                    return categoryNode;
                })
                .collect(Collectors.toList());

        List<CategoryNode> resultList = list.stream()
                .filter(categoryNode -> categoryNode.getParentId().equals("0"))
                .map(categoryNode -> categoryUtil.getChildrenNode(categoryNode, list))
                .collect(Collectors.toList());

        CategoryNode rootNode = new CategoryNode();
        rootNode.setCategoryName("根类别");
        rootNode.setId("0");
        rootNode.setChildren(resultList);
        return CommonResult.success(rootNode);
    }

    @Override
    public ResponseResult getCategoryChildrenList(String search_str, String category_id, Integer pageNum, Integer pageSize) {
        if (!category_id.equals("") && !category_id.equals("0")) {
            SmsAssetCategoryManagement categoryManagement = smsAssetCategoryManagementMapper.selectById(category_id);
            if (categoryManagement == null || isNullOrEmpty(categoryManagement.getId())) {
                return CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_NOT_EXIST);
            }
        }

        Page<SmsAssetCategoryManagement> page = new Page<>(pageNum, pageSize);
        QueryWrapper<SmsAssetCategoryManagement> queryWrapper = new QueryWrapper<>();
        if (!isNullOrEmpty(category_id)) {
            queryWrapper.lambda()
                    .eq(SmsAssetCategoryManagement::getParentId, category_id);
        }
        if (!isNullOrEmpty(search_str)) {
            queryWrapper.lambda()
                    .like(SmsAssetCategoryManagement::getCategoryName, search_str);
        }
        queryWrapper.orderByAsc("id*1");

        smsAssetCategoryManagementMapper.selectPage(page, queryWrapper);
        List<SmsAssetCategoryManagementResp> respList = page.getRecords()
                .stream()
                .map(category -> {
                    SmsAssetCategoryManagementResp resp = new SmsAssetCategoryManagementResp();
                    BeanUtils.copyProperties(category, resp);

                    SmsAssetCategoryManagement categoryManagement = smsAssetCategoryManagementMapper.selectById(category.getRootParentId());
                    if (categoryManagement != null && !isNullOrEmpty(categoryManagement.getId())) {
                        resp.setRootCategoryName(categoryManagement.getCategoryName());
                    }
                    return resp;
                })
                .collect(Collectors.toList());
        int total = (int) page.getTotal();
        return CommonResult.success(respList, total);
    }

    @Override
    public ResponseResult updateCategory(SmsAssetCategoryManagementReq categoryReq) {
        if (isNullOrEmpty(categoryReq.getId()) || isNullOrEmpty(categoryReq.getCategoryName())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        SmsAssetCategoryManagement categoryManagement = smsAssetCategoryManagementMapper.selectById(categoryReq.getId());
        if (categoryManagement == null || isNullOrEmpty(categoryManagement.getId())) {
            return CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_NOT_EXIST);
        }

        if (categoryManagement.getIsCanDelete() == CATEGORY_DELETE_FLAG_FALSE) {
            return CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_CAN_NOT_UPDATE);
        }

        if (!categoryManagement.getCategoryName().equals(categoryReq.getCategoryName())) {
            Integer repeatCount = smsAssetCategoryManagementMapper.selectCount(new QueryWrapper<SmsAssetCategoryManagement>()
                    .lambda()
                    .eq(SmsAssetCategoryManagement::getCategoryName, categoryReq.getCategoryName()));
            if (repeatCount > 0) {
                return CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_REPEAT);
            }

            SmsAssetCategoryManagement updateCategory = new SmsAssetCategoryManagement();
            updateCategory.setId(categoryReq.getId());
            updateCategory.setCategoryName(categoryReq.getCategoryName());
            smsAssetCategoryManagementMapper.updateById(updateCategory);
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult deleteCategory(SmsAssetCategoryManagementReq categoryReq) {
        if (isNullOrEmpty(categoryReq.getId())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //判断子类别
        Integer categoryChildCount = smsAssetCategoryManagementMapper.selectCount(new LambdaQueryWrapper<SmsAssetCategoryManagement>()
                .eq(SmsAssetCategoryManagement::getParentId,categoryReq.getId()));
        if (isNullOrEmpty(categoryChildCount) || categoryChildCount > 0){
            return CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_DELETE_FAIL_HAS_CHILD_NODE);
        }

        //判断库存中是否含有此类别
        Integer storageCount = smsAssetFixedStorageMapper.selectCount(new LambdaQueryWrapper<SmsAssetFixedStorage>()
                .eq(SmsAssetFixedStorage::getAssetCategory,categoryReq.getId()));
        if (isNullOrEmpty(storageCount) || storageCount > 0){
            return CommonResult.failed(CommonCodeEnum.ASSET_CATEGORY_DELETE_FAIL_HAS_STORAGE);
        }

        smsAssetCategoryManagementMapper.deleteById(categoryReq.getId());
        return CommonResult.success();
    }
}
